feat(core,isthmus): add DynamicParameter expression support#752
feat(core,isthmus): add DynamicParameter expression support#752bvolpato wants to merge 1 commit intosubstrait-io:mainfrom
Conversation
|
Do you plan to also work on implementing the |
## Summary Add full support for `DynamicParameter` expressions and plan-level `DynamicParameterBinding`, enabling parameterized queries in substrait-go. This mirrors the functionality recently added in [substrait-java#752](substrait-io/substrait-java#752), ensuring Go consumers can create and read plans containing dynamic parameters. ## Changes ### Expression (`expr/expression.go`) - New `DynamicParameter` struct implementing the full `Expression` interface (`String`, `ToProto`, `Equals`, `Visit`, `IsScalar`, `GetType`, `ToProtoFuncArg`) - Proto deserialization in `ExprFromProto()` with nil safety check ### Builder (`expr/builder.go`) - `ExprBuilder.DynamicParam(outputType, paramRef)` method with `dynamicParamBuilder` - Implements `BuildExpr()` and `BuildFuncArg()` for use as function arguments ### Plan bindings (`plan/common.go`, `plan/plan.go`, `plan/builders.go`) - `DynamicParameterBinding` struct mapping parameter anchors to literal values - `Plan.ParameterBindings()` accessor - `FromProto()` / `ToProto()` serialization for parameter bindings - `Builder.PlanWithBindings()` method on the `Builder` interface ## Testing 17 new tests across two test files: - `expr/dynamic_parameter_test.go` — 11 tests covering basic construction, nullability, equality, visit, proto roundtrip (5 types), nil proto error, builder (3 cases), builder as function argument, and multiple parameters - `plan/dynamic_parameter_test.go` — 6 tests covering filter plan with bindings, project plan, multiple bindings, no bindings, JSON parsing roundtrip, and end-to-end builder usage All existing tests continue to pass with zero regressions.
a1807e4 to
96bcc42
Compare
|
Thanks @nielspardon! Great question. I've rebased this PR on the latest Regarding I think it makes sense to handle
I'll open a follow-up issue to track |
I wasn't suggesting that it should be included in this PR. I was simply asking whether you were planning to also look into |
bvolpato
left a comment
There was a problem hiding this comment.
👋 Checking in on this PR. @nielspardon left some helpful review feedback on March 18 & 24 about test consistency - specifically that some test cases only assert the type while others only assert the parameter reference, and suggested checking both consistently.
This PR has been open for a month - are you planning to address the review feedback? If you're waiting on further review from maintainers, a gentle ping might help move it forward.
|
(disregard the comment above, I was testing some automation!) |
Implement full support for Substrait DynamicParameter expressions, enabling parameterized placeholders in plan bodies instead of embedded literals. This maps bidirectionally to Calcite's RexDynamicParam (JDBC ? bind parameters). Changes: - Add Expression.DynamicParameter POJO with type and parameterReference - Wire visitor pattern across all expression visitors - Add proto conversion (POJO<->Proto) in both directions - Add Calcite conversion (RexDynamicParam<->DynamicParameter) - Replace UnsupportedOperationException in visitDynamicParam - Add debug stringification in ExpressionStringify - Add 20 tests covering proto roundtrips, Calcite conversions, and full end-to-end roundtrips
96bcc42 to
1416c34
Compare
|
[review-prs-verification] Files reviewed.
Tests/checks run and results.
Fixes committed/pushed, if any.
Final CI status.
|
Summary
Add full support for Substrait
DynamicParameterexpressions, enabling parameterized placeholders (analogous to JDBC?bind parameters) in plan bodies instead of embedded literals. This maps bidirectionally to Calcite'sRexDynamicParam.DynamicParameter enables plan reuse — the same plan structure can be compiled and cached once, then executed with different parameter values without re-planning. This is essential for prepared statement workflows and for exchanging plans between engines without leaking literal values.
Changes
Core POJO + Proto layer:
Expression.DynamicParameter— immutable POJO withtypeandparameterReferencefieldsExpressionVisitor/AbstractExpressionVisitor— newvisit(DynamicParameter)methodExpressionProtoConverter— POJO→Proto conversionProtoExpressionConverter— Proto→POJO conversion (DYNAMIC_PARAMETERcase)ExpressionCopyOnWriteVisitor— leaf-node handling (returnsOptional.empty())Calcite integration (isthmus):
RexExpressionConverter.visitDynamicParam()— replacesUnsupportedOperationExceptionwith actual Calcite→Substrait conversionExpressionRexConverter.visit(DynamicParameter)— Substrait→Calcite conversionDebug support:
ExpressionStringify— added DynamicParameter stringificationTesting
20 tests total, all passing:
DynamicParameterRoundtripTestin core) — POJO↔Proto↔POJO for I64, nullable STRING, FP64, I32, DATE, BOOLEAN, DECIMAL, TIMESTAMPDynamicParameterTest) — direct Calcite↔Substrait conversions and project roundtripsDynamicParameterRoundtripTestin isthmus) — filter/projection/multi-type POJO roundtrips, Calcite-originated RexDynamicParam roundtrips, and full Substrait→Calcite→Substrait bidirectional roundtripsAll existing tests in
coreandisthmuscontinue to pass with zero regressions. PMD and Spotless checks are clean.